#include <dw_net.h>
#include <chrono>
#include <iostream>

enum class MsgTypes : uint32_t
{
    ServerAccept,
    ServerDeny,
    ServerPing,
    MessageAll,
    ServerMessage,
    AssignID
};

uint32_t dw::net::Scramble(uint32_t in)
{
    return in / 2;
}

class CustomClient : public dw::net::client_interface<MsgTypes>
{
public:
    void PingServer()
    {
        dw::net::message<MsgTypes> msg(MsgTypes::ServerPing);

        std::chrono::system_clock::time_point timeNow = std::chrono::system_clock::now();

        msg << timeNow;
        Send(msg);
    }

    void MessageAll()
    {
        dw::net::message<MsgTypes> msg(MsgTypes::MessageAll);
        Send(msg);
    }
};

int main()
{
    CustomClient c;
    c.Connect("43.142.137.93", 60000);

    bool key[3] = {false, false, false};
    bool old_key[3] = {false, false, false};

    bool bQuit = false;
    while (!bQuit)
    {
        if (GetForegroundWindow() == GetConsoleWindow())
        {
            key[0] = GetAsyncKeyState('1') & 0x8000;
            key[1] = GetAsyncKeyState('2') & 0x8000;
            key[2] = GetAsyncKeyState('3') & 0x8000;
        }

        if (key[0] && !old_key[0])
            c.PingServer();
        if (key[1] && !old_key[1])
            c.MessageAll();
        if (key[2] && !old_key[2])
            bQuit = true;

        for (int i = 0; i < 3; i++)
            old_key[i] = key[i];

        if (c.IsConnected())
        {
            if (!c.Incomming().empty())
            {
                DW_PRINT_FUNC_START
                auto msg = c.Incomming().pop_front().msg;

                switch (msg.header.type)
                {
                case MsgTypes::ServerAccept:
                {
                    std::cout << "Server Accepted Connection!" << std::endl;
                }
                break;

                case MsgTypes::ServerPing:
                {
                    std::chrono::system_clock::time_point timeNow = std::chrono::system_clock::now();
                    std::chrono::system_clock::time_point timeThen;
                    msg >> timeThen;
                    std::cout << "Ping: " << std::chrono::duration<double>(timeNow - timeThen).count() << std::endl;
                }
                break;

                case MsgTypes::ServerMessage:
                {
                    uint32_t clientID;
                    msg >> clientID;
                    std::cout << "Hello from [" << clientID << "]" << std::endl;
                }
                break;

                case MsgTypes::AssignID:
                {
                    uint32_t clientID;
                    msg >> clientID;
                    clientID = ntohl(clientID);
                    std::cout << "Assigned ID: " << clientID << std::endl;
                }
                break;
                }
            }
        }
        else
        {
            std::cout << "Lost Connection to Server!" << std::endl;
            bQuit = true;
        }
    }

    return 0;
}